4.7 🔥 Разработка приложения Sushi App. Часть 1
6 из 6 шагов пройдено

 Разработка приложения Sushi App. Часть 1

➡️Ссылка на репозиторий с кодом этого урока (ветка main)

Данные и модели

Теперь интересный и новый материал. Обычно данные для подобных приложений, загружаются из базы данных. В данном случае для упрощения, мы подготовим локальные данные и будем хранить их внутри приложения.

В папку models добавим файл roll.dart
В папку data добавим файл rolls_data.dart

Файл roll.dart

/// Модель ролла, используемая для хранения его данных.  
///  
/// Каждый объект (экземпляр) класса Roll содержит информацию о ролле:  
/// Имя, описание, URL-адрес изображения и цену.  
///  
/// Используется в сочетании с виджетом [RollCard] для отображения  
/// информации о ролле на экране.  
class Roll {  
  final int id;  
  final String name;  
  final String description;  
  final String fullDescription;  
  final String imageUrl;  
  final double price;  
  
  Roll({  
    required this.id,  
    required this.name,  
    required this.description,  
    required this.fullDescription,  
    required this.imageUrl,  
    required this.price,  
  });  
}

Файл rolls_data.dart

// Данные о роллах  
import '../models/roll.dart';  
  
final List<Roll> data = [  
  Roll(  
    id: 1,  
    name: "Филадельфия",  
    description: "Лосось, сыр, авокадо",  
    imageUrl: "assets/images/roll1.png",  
    price: 450.0,  
    fullDescription:  
        "Филадельфия - это классический ролл, созданный для истинных гурманов. Сочетание свежего лосося, нежного сыра и авокадо создает неповторимый вкус. Этот ролл, с вдохновением названный в честь города Филадельфия, завоевал сердце миллионов благодаря своей изысканности и балансу ингредиентов.",  
  ),  
  Roll(  
    id: 2,  
    name: "Калифорния",  
    description: "Краб, авокадо, икра",  
    imageUrl: "assets/images/roll2.png",  
    price: 500.0,  
    fullDescription:  
        "Калифорния - это ролл, который откроет вам новые горизонты вкуса. Сладкий краб в сочетании со свежестью авокадо и пикантной икрой - идеальный выбор для тех, кто ищет экзотические впечатления. Этот ролл был создан в Калифорнии и быстро стал хитом среди любителей суши за его уникальный вкус и презентацию.",  
  ),  
  Roll(  
    id: 3,  
    name: "Дракон",  
    description: "Угорь, авокадо, кунжут",  
    imageUrl: "assets/images/roll3.png",  
    price: 550.0,  
    fullDescription:  
        "Дракон - это ролл, который всегда будет в центре внимания. Нежный угорь в сочетании с кремовым авокадо и хрустящим кунжутом создает незабываемый вкус. Этот ролл не только порадует вас своими вкусовыми качествами, но и удивит своей великолепной подачей и загадочной историей создания.",  
  ),  
  Roll(  
    id: 4,  
    name: "Ролл с креветкой",  
    description: "Креветка, огурец, соус",  
    imageUrl: "assets/images/roll4.png",  
    price: 400.0,  
    fullDescription:  
        "Ролл с креветкой - это легкое и освежающее блюдо, которое понравится каждому. Сочные креветки, свежий огурец и уникальный соус делают этот ролл идеальным выбором для тех, кто ищет что-то особенное. Это блюдо, созданное на основе традиционных рецептов, станет настоящим украшением вашего стола.",  
  ),  
  Roll(  
    id: 5,  
    name: "Вегетарианский ролл",  
    description: "Огурец, авокадо, перец",  
    imageUrl: "assets/images/roll5.png",  
    price: 350.0,  
    fullDescription:  
        "Вегетарианский ролл - это праздник для всех любителей овощей. Сочетание свежих огурцов, мягкого авокадо и сочного перца создают легкий и вкусный ролл, который подойдет как для вегетарианцев, так и для тех, кто хочет сделать паузу от мяса.",  
  ),  
  Roll(  
    id: 6,  
    name: "Запеченный ролл",  
    description: "Лосось, сыр, спайси соус",  
    imageUrl: "assets/images/roll6.png",  
    price: 600.0,  
    fullDescription:  
        "Запеченный ролл - это шедевр японской кухни. Сочетание нежного лосося, кремового сыра и острого спайси соуса создают уникальный вкус, который невозможно забыть. Этот ролл, запеченный до совершенства, станет вашим любимым блюдом, которое вы захотите заказывать снова и снова.",  
  ),  
  Roll(  
    id: 7,  
    name: "Подозрительный ролл",  
    description: "Хммм ...",  
    imageUrl: "assets/images/roll7.png",  
    price: 9999.0,  
    fullDescription:  
        "Ты не станешь неуязвимым, но… Можешь почувствовать себя: Богом интерьерного дизайна, потому что ковёр начнёт двигаться, как океан. Избранным, которому открылись тайны вселенной (спойлер: утром ты их не вспомнишь). Персонажем триллера, когда поймёшь, что твои руки — это на самом деле ноги.",  
  ),  
];

Теперь нужно правильно использовать эти данные!

Исправим код карточки RollCard. Теперь вместо значений, которые были прописаны вручную, мы укажем ссылки на объект Roll

Файл roll_card.dart

import 'package:flutter/material.dart';

import '../models/roll.dart';


class RollCard extends StatelessWidget {

  final Roll roll; // Переменная для хранения данных о ролле
  
  const RollCard({super.key, required this.roll});

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () {},
      child: Card(
        color: Colors.white,
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Expanded(
                child: ClipRRect(
                  borderRadius: const BorderRadius.only(
                    topLeft: Radius.circular(12),
                    topRight: Radius.circular(12),
                  ),
                  child: Image.asset(
                    roll.imageUrl, // Путь к изображению через объект roll
                    width: double.infinity,
                    fit: BoxFit.cover,
                  ),
                ),
              ),
              Expanded(
                child: ListTile(
                  contentPadding: EdgeInsets.zero,
                  title: Text(roll.name), // Название ролла через объект roll
                  subtitle: Text(
                    roll.description, // Описание ролла через объект roll
                    style: const TextStyle(fontSize: 10),
                  ),
                ),
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text("${roll.price} руб."), // Цена ролла через объект roll
                  TextButton(
                    onPressed: () {
                      // Здесь можно добавить логику покупки
                    },
                    child: const Text("Купить"),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Далее нужно при вызове виджета RollCard передавать в него данные по индексу из массива с настоящими данными

Файл main_screen.dart

import 'package:flutter/material.dart';

import '../models/roll.dart';
import '../data/rolls_data.dart';
import '../widgets/roll_card.dart';


class MainScreen extends StatefulWidget {
  MainScreen({super.key});

  @override
  State<MainScreen> createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  
  final List<Roll> rolls = data; // Данные для списка роллов

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Sushi Shop'),
        actions: <Widget>[
          IconButton(
            icon: Badge.count(count: 99, child: const Icon(Icons.shopping_cart)),
            tooltip: 'Корзина',
            // Чтобы Badge обновился при возврате назад на этот экран
            onPressed: ()  {

            },
          ),
        ],
      ),

      body: GridView.builder(
        padding: const EdgeInsets.symmetric(horizontal: 12),
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 2, // Указываем количество колонок
          crossAxisSpacing: 8.0, // Отступ между колонками
          mainAxisSpacing: 8.0, // Отступ между строками
          childAspectRatio: 0.85, // Соотношение сторон карточки
        ),
        itemCount: rolls.length, // Количество элементов в списке
        itemBuilder: (context, index) {
          return RollCard(
            roll: rolls[index],
          );
        },
      ),
    );
  }
}

Есть массив rolls объектов Roll с конкретными данными из файла rolls_data.dart

final List<Roll> rolls = data; // Данные для списка роллов

Виджет GridView создаёт в цикле каждый элемент списка, передавая индекс от 0 до длины массива с роллами rolls.length
В виджет RollCard передается объект из массива по определенному индексу.
Cначала создается карточка с данными из массива по индексу 0, потом по индексу 1 и т.д.

itemCount: rolls.length, // Количество элементов в списке
itemBuilder: (context, index) {
  return RollCard(
    roll: rolls[index],
  );
},

В результате экране будет список всех товаров из файла с данными rolls_data.dart


Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий